package org.jmc.refmanager.web.wicket.security;

import org.apache.wicket.Request;
import org.apache.wicket.authentication.AuthenticatedWebSession;
import org.apache.wicket.authorization.strategies.role.Roles;
import org.apache.wicket.injection.web.InjectorHolder;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class RefManagerAuthenticatedWebSession extends AuthenticatedWebSession {
	private static final long serialVersionUID = 1L;
	private static final Logger logger = LoggerFactory
			.getLogger(RefManagerAuthenticatedWebSession.class);

	@SpringBean(name="authenticationManager")
	private AuthenticationManager authenticationManager;

	public RefManagerAuthenticatedWebSession(Request request) {
		super(request);
		InjectorHolder.getInjector().inject(this);
	}

	@Override
	public boolean authenticate(String username, String password) {
		boolean authenticated = false;
		Authentication authentication = null;
		try {
			authentication = authenticationManager.authenticate(
							new UsernamePasswordAuthenticationToken(
							username, password));
			SecurityContextHolder.getContext().setAuthentication(authentication);
			authenticated = authentication.isAuthenticated();
		} catch (AuthenticationException e) {
			logger.warn(String.format("User '%s' failed to login. Reason: %s",
					username, e.getMessage()));
			authenticated = false;
		}
		return authenticated;
	}

	@Override
	public Roles getRoles() {
		Roles roles = new Roles();
		getRolesIfSignedIn(roles);
		return roles;
	}

	private void getRolesIfSignedIn(Roles roles) {
		if (isSignedIn()) {
			Authentication authentication = SecurityContextHolder.getContext()
					.getAuthentication();
			addRolesFromAuthentication(roles, authentication);
		}
	}

	private void addRolesFromAuthentication(Roles roles, Authentication authentication) {
		for (GrantedAuthority authority : authentication.getAuthorities()) {
			roles.add(authority.getAuthority());
		}
	}

	/**
     * Signout, invalidates the session. 
     * After a signout, you should redirect 
     * the browser to the home page.
     */
	@Override
	public void signOut() {
		super.signOut();
//        YourAppUserDetails user = getUser();
//        if (user != null) {
//            logger.info("Logout by user '" + user.getUsername() + "'.");
//        }
        setAuthentication(null);
        invalidate();
    }

    /**
     * Sets the Spring Security authentication.
     * @param authentication the authentication or null to clear
     */
    private void setAuthentication(Authentication authentication) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

}
